package kino.timeevent;

import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;

/**
 * 时间事件注册器
 */
public class KinoTimeEventRegistry {
    /**
     * 时间事件队列
     * @return
     */
    private PriorityQueue<TimeEvent> eventQueue;

    public KinoTimeEventRegistry() {
        // 时间事件队列 基于 最近待执行时间排序
        this.eventQueue = new PriorityQueue<>((o1, o2) -> {
            Long o1Next = o1.getLastExecutionEventTime() + o1.getInterval();
            Long o2Next = o2.getLastExecutionEventTime() + o2.getInterval();
            return (int)(o1Next - o2Next);
        });
        // 注册时间事件
        this.register();
    }

    /**
     * 时间事件注册方法，该方法逐个构造时间事件
     */
    public void register() {
        Long curTime = System.currentTimeMillis();
        // serverCron 每秒执行一次
        eventQueue.add(new ServerCronTimeEvent(curTime, 5000L));
    }

    /**
     * 获取最近待执行时间事件 待执行时间
     * @return
     */
    public Long getNextTimeEventTime() {
        TimeEvent nextTimeEvent = eventQueue.peek();
        return nextTimeEvent != null ? nextTimeEvent.getLastExecutionEventTime() + nextTimeEvent.getInterval() : 1000L;
    }

    /**
     * 获取当前时间下已就绪的时间事件
     * @return
     */
    public List<TimeEvent> getReadyTimeEvent() {
        Long curTime = System.currentTimeMillis();
        List<TimeEvent> readyTimeEventList = new ArrayList<>();
        while (!eventQueue.isEmpty() && (curTime > eventQueue.peek().getLastExecutionEventTime() + eventQueue.peek().getInterval())) {
            readyTimeEventList.add(eventQueue.poll());
        }
        return readyTimeEventList;
    }

    /**
     * 重新设置时间事件到等待队列中
     * @param timeEventList
     */
    public void reSetTimeEvent(List<TimeEvent> timeEventList) {
        for (TimeEvent timeEvent : timeEventList) {
            eventQueue.add(timeEvent);
        }
    }
}
